package com.dayaokeji.imkitwrapper.fragment;


import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import com.beetle.bauhinia.GroupMessageActivity;
import com.beetle.bauhinia.PeerMessageActivity;
import com.beetle.bauhinia.db.ConversationIterator;
import com.beetle.bauhinia.db.CustomerMessageDB;
import com.beetle.bauhinia.db.GroupMessageDB;
import com.beetle.bauhinia.db.ICustomerMessage;
import com.beetle.bauhinia.db.IMessage;
import com.beetle.bauhinia.db.MessageIterator;
import com.beetle.bauhinia.db.PeerMessageDB;
import com.beetle.bauhinia.tools.Notification;
import com.beetle.bauhinia.tools.NotificationCenter;
import com.beetle.im.GroupMessageObserver;
import com.beetle.im.IMMessage;
import com.beetle.im.IMService;
import com.beetle.im.IMServiceObserver;
import com.beetle.im.PeerMessageObserver;
import com.beetle.im.SystemMessageObserver;
import com.dayaokeji.imkitwrapper.adapter.ConversationAdapter;
import com.dayaokeji.imkitwrapper.R;
import com.dayaokeji.imkitwrapper.bean.Conversation;
import com.dayaokeji.imkitwrapper.init.Constant;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;

/**
 * message list
 */
public class MessageListFragment extends BaseFragment implements IMServiceObserver,
        PeerMessageObserver, GroupMessageObserver, SystemMessageObserver, AdapterView.OnItemClickListener,
        NotificationCenter.NotificationCenterObserver{
    private static final String TAG = MessageListFragment.class.getSimpleName();

    private static final String EXTRA_UID = "u_id";

    private ListView lvConversations;

    private long currentUID = 0;
    private List<Conversation> conversations = new ArrayList<Conversation>();;
    private ConversationAdapter adapter;
    private static final long APPID = 7;
    private static final long KEFU_ID = 55;
    private ConversationOnItemClickListener conversationOnItemClickListener;
    private UserInfoCallback userInfoCallback;
    private GroupInfoCallback groupInfoCallback;

    public static MessageListFragment newInstance(long uid) {
        
        Bundle args = new Bundle();
        args.putLong(EXTRA_UID, uid);
        MessageListFragment fragment = new MessageListFragment();
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final View rootView = inflater.inflate(R.layout.fragment_conversation, container, false);
        lvConversations = rootView.findViewById(R.id.lv_conversations);
        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        currentUID = getArguments().getLong(EXTRA_UID);
        if (currentUID == 0) {
            Log.e(TAG, "current uid is 0");
            return;
        }


        IMService im =  IMService.getInstance();
        im.addObserver(this);
        im.addPeerObserver(this);
        im.addGroupObserver(this);
        im.addSystemObserver(this);

        loadConversations();

        lvConversations.addHeaderView(createHeaderView("通","通知"));
        lvConversations.addHeaderView(createHeaderView("群","群组"));

        adapter = new ConversationAdapter(getActivity());
        adapter.setConversations(conversations);
        lvConversations.setAdapter(adapter);
        lvConversations.setOnItemClickListener(this);


        NotificationCenter nc = NotificationCenter.defaultCenter();
        nc.addObserver(this, PeerMessageActivity.SEND_MESSAGE_NAME);
        nc.addObserver(this, PeerMessageActivity.CLEAR_MESSAGES);
        nc.addObserver(this, GroupMessageActivity.SEND_MESSAGE_NAME);
        nc.addObserver(this, GroupMessageActivity.CLEAR_MESSAGES);
    }

    private View createHeaderView(String avatarName, String title) {
        View headerView = getLayoutInflater().inflate(R.layout.meesage_list_header, null, false);
        TextView tvAvatarName = headerView.findViewById(R.id.tv_avatar_name);
        TextView tvTitle = headerView.findViewById(R.id.tv_title);
        tvAvatarName.setText(avatarName);
        tvTitle.setText(title);
        return headerView;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        IMService im =  IMService.getInstance();
        im.removeObserver(this);
        im.removePeerObserver(this);
        im.removeGroupObserver(this);
        im.removeSystemObserver(this);
        NotificationCenter nc = NotificationCenter.defaultCenter();
        nc.removeObserver(this);
    }


    public  String messageContentToString(IMessage.MessageContent content) {
        if (content instanceof IMessage.Text) {
            return ((IMessage.Text) content).text;
        } else if (content instanceof IMessage.Image) {
            return "一张图片";
        } else if (content instanceof IMessage.Audio) {
            return "一段语音";
        } else if (content instanceof IMessage.GroupNotification) {
            return ((IMessage.GroupNotification) content).description;
        } else if (content instanceof IMessage.Location) {
            return "一个地理位置";
        } else {
            return content.getRaw();
        }
    }

    void updateConversationDetail(Conversation conv) {
        String detail = messageContentToString(conv.message.content);
        conv.setDetail(detail);
    }

    void updatePeerConversationName(Conversation conv) {
        User u = getUser(conv.cid);
        if (TextUtils.isEmpty(u.name)) {
            conv.setName(u.identifier);
            final Conversation fconv = conv;
            asyncGetUser(conv.cid, new GetUserCallback() {
                @Override
                public void onUser(User u) {
                    fconv.setName(u.name);
                    fconv.setAvatar(u.avatarURL);
                }
            });
        } else {
            conv.setName(u.name);
        }
        conv.setAvatar(u.avatarURL);
    }

    void updateGroupConversationName(Conversation conv) {
        Group g = getGroup(conv.cid);
        if (TextUtils.isEmpty(g.name)) {
            conv.setName(g.identifier);
            final Conversation fconv = conv;
            asyncGetGroup(conv.cid, new GetGroupCallback() {
                @Override
                public void onGroup(Group g) {
                    fconv.setName(g.name);
                    fconv.setAvatar(g.avatarURL);
                }
            });
        } else {
            conv.setName(g.name);
        }
        conv.setAvatar(g.avatarURL);
    }

    void loadConversations() {
        ConversationIterator iter = PeerMessageDB.getInstance().newConversationIterator();
        if (iter != null) {
            while (true) {
                IMessage msg = iter.next();
                if (msg == null) {
                    break;
                }
                long id = (this.currentUID == msg.sender) ? msg.receiver : msg.sender;
                Conversation conv = new Conversation();
                conv.type = Conversation.CONVERSATION_PEER;
                conv.message = msg;
                conv.cid = id;
                updatePeerConversationName(conv);
                updateConversationDetail(conv);
                conversations.add(conv);
            }
        }

        iter = GroupMessageDB.getInstance().newConversationIterator();
        if (iter != null) {
            while (true) {
                IMessage msg = iter.next();
                if (msg == null) {
                    break;
                }
                Conversation conv = new Conversation();
                conv.type = Conversation.CONVERSATION_GROUP;
                conv.message = msg;
                conv.cid = msg.receiver;

                updateGroupConversationName(conv);
                updateNotificationDesc(conv);
                updateConversationDetail(conv);
                conversations.add(conv);
            }
        }

        MessageIterator messageIterator  = CustomerMessageDB.getInstance().newMessageIterator(KEFU_ID);
        ICustomerMessage msg = null;
        while (messageIterator != null) {
            msg = (ICustomerMessage) messageIterator.next();
            if (msg == null) {
                break;
            }

            if (msg.content.getType() != IMessage.MessageType.MESSAGE_ATTACHMENT) {
                break;
            }
        }
        if (msg == null) {
            msg = new ICustomerMessage();
            msg.isSupport = true;
            msg.isOutgoing = false;
            msg.customerAppID = APPID;
            msg.customerID = currentUID;
            msg.storeID = KEFU_ID;
            msg.sellerID = 0;

            msg.content = IMessage.newText("如果你在使用过程中有任何问题和建议，记得给我们发信反馈哦");
            msg.sender = 0;
            msg.receiver = this.currentUID;
            msg.timestamp = now();
        }
        Conversation conv = new Conversation();
        conv.message = msg;
        conv.cid = 0;
        conv.type = Conversation.CONVERSATION_CUSTOMER_SERVICE;
        conv.setName("客服");
        updateConversationDetail(conv);
//        conversations.add(conv);

        Comparator<Conversation> cmp = new Comparator<Conversation>() {
            public int compare(Conversation c1, Conversation c2) {
                if (c1.message.timestamp > c2.message.timestamp) {
                    return -1;
                } else if (c1.message.timestamp == c2.message.timestamp) {
                    return 0;
                } else {
                    return 1;
                }

            }
        };
        Collections.sort(conversations, cmp);
    }

    public static class User {
        public long uid;
        public String name;
        public String avatarURL;

        //name为nil时，界面显示identifier字段
        public String identifier;
    }

    public static class Group {
        public long gid;
        public String name;
        public String avatarURL;

        //name为nil时，界面显示identifier字段
        public String identifier;
    }

    public void delAndExistGroup(long gid) {
        for (Conversation conversation : conversations) {
            if (conversation.cid == gid && conversation.type == Conversation.CONVERSATION_GROUP) {
                GroupMessageDB.getInstance().clearCoversation(gid);
                conversations.remove(conversation);
                adapter.notifyDataSetChanged();
            }
        }
    }

    public interface GetUserCallback {
        void onUser(User u);
    }

    public interface GetGroupCallback {
        void onGroup(Group g);
    }

    //消息列表点击
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
                            long id) {
        if (position == 0) {//通知
            if (conversationOnItemClickListener != null) {
                conversationOnItemClickListener.onNotice();
            }
        }else if (position == 1) {//群组
            if (conversationOnItemClickListener != null) {
                conversationOnItemClickListener.onGroups();
            }
        }else {//消息
            Conversation conv = conversations.get(position-lvConversations.getHeaderViewsCount());
            Log.i(TAG, "conv:" + conv.getName());
            if (conv.type == Conversation.CONVERSATION_PEER) {
                onPeerClick(conv.cid);
            } else if (conv.type == Conversation.CONVERSATION_GROUP){
                onGroupClick(conv.cid);
            } else if (conv.type == Conversation.CONVERSATION_CUSTOMER_SERVICE) {
                onCustomerServiceClick(conv);
            }
        }
    }

    @Override
    public void onConnectState(IMService.ConnectState state) {

    }
    @Override
    public void onPeerInputting(long uid) {

    }
    @Override
    public void onPeerMessage(IMMessage msg) {
        Log.i(TAG, "on peer message");
        IMessage imsg = new IMessage();
        imsg.timestamp = now();
        imsg.msgLocalID = msg.msgLocalID;
        imsg.sender = msg.sender;
        imsg.receiver = msg.receiver;
        imsg.setContent(msg.content);

        long cid = 0;
        if (msg.sender == this.currentUID) {
            cid = msg.receiver;
        } else {
            cid = msg.sender;
        }

        int pos = findConversationPosition(cid, Conversation.CONVERSATION_PEER);
        Conversation conversation = null;
        if (pos == -1) {
            conversation = newPeerConversation(cid);
        } else {
            conversation = conversations.get(pos);
        }

        conversation.message = imsg;
        updateConversationDetail(conversation);

        if (pos == -1) {
            conversations.add(0, conversation);
            adapter.notifyDataSetChanged();
//            adapter.setConversations(conversations);
//            lvConversations.setAdapter(adapter);
        } else if (pos > 0) {
            conversations.remove(pos);
            conversations.add(0, conversation);
//            adapter.setConversations(conversations);
//            lvConversations.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        } else {
            //pos == 0
        }
    }

    public Conversation findConversation(long cid, int type) {
        for (int i = 0; i < conversations.size(); i++) {
            Conversation conv = conversations.get(i);
            if (conv.cid == cid && conv.type == type) {
                return conv;
            }
        }
        return null;
    }

    public int findConversationPosition(long cid, int type) {
        for (int i = 0; i < conversations.size(); i++) {
            Conversation conv = conversations.get(i);
            if (conv.cid == cid && conv.type == type) {
                return i;
            }
        }
        return -1;
    }

    public Conversation newPeerConversation(long cid) {
        Conversation conversation = new Conversation();
        conversation.type = Conversation.CONVERSATION_PEER;
        conversation.cid = cid;

        updatePeerConversationName(conversation);
        return conversation;
    }

    public Conversation newGroupConversation(long cid) {
        Conversation conversation = new Conversation();
        conversation.type = Conversation.CONVERSATION_GROUP;
        conversation.cid = cid;
        updateGroupConversationName(conversation);
        return conversation;
    }

    public static int now() {
        Date date = new Date();
        long t = date.getTime();
        return (int)(t/1000);
    }
    @Override
    public void onPeerMessageACK(int msgLocalID, long uid) {
        Log.i(TAG, "message ack on main");
    }

    @Override
    public void onPeerMessageFailure(int msgLocalID, long uid) {
    }

    @Override
    public void onGroupMessage(IMMessage msg) {
        Log.i(TAG, "on group message");
        IMessage imsg = new IMessage();
        imsg.timestamp = msg.timestamp;
        imsg.msgLocalID = msg.msgLocalID;
        imsg.sender = msg.sender;
        imsg.receiver = msg.receiver;
        imsg.setContent(msg.content);

        int pos = findConversationPosition(msg.receiver, Conversation.CONVERSATION_GROUP);
        Conversation conversation = null;
        if (pos == -1) {
            conversation = newGroupConversation(msg.receiver);
        } else {
            conversation = conversations.get(pos);
        }

        conversation.message = imsg;
        updateConversationDetail(conversation);

        if (pos == -1) {
            conversations.add(0, conversation);
//            adapter.setConversations(conversations);
//            lvConversations.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        } else if (pos > 0) {
            conversations.remove(pos);
            conversations.add(0, conversation);
//            adapter.setConversations(conversations);
//            lvConversations.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        } else {
            //pos == 0
        }
    }
    @Override
    public void onGroupMessageACK(int msgLocalID, long uid) {

    }

    @Override
    public void onGroupMessageFailure(int msgLocalID, long uid) {

    }

    @Override
    public void onGroupNotification(String text) {
        IMessage.GroupNotification groupNotification = IMessage.newGroupNotification(text);
        IMessage imsg = new IMessage();
        imsg.sender = 0;
        imsg.receiver = groupNotification.groupID;
        imsg.timestamp = groupNotification.timestamp;
        imsg.setContent(groupNotification);
        int pos = findConversationPosition(groupNotification.groupID, Conversation.CONVERSATION_GROUP);
        Conversation conv = null;
        if (pos == -1) {
            conv = newGroupConversation(groupNotification.groupID);
        } else {
            conv = conversations.get(pos);
        }
        conv.message = imsg;
        updateNotificationDesc(conv);
        updateConversationDetail(conv);
        if (pos == -1) {
            conversations.add(0, conv);
            adapter.notifyDataSetChanged();
        } else if (pos > 0) {
            //swap with 0
            conversations.remove(pos);
            conversations.add(0, conv);
            adapter.notifyDataSetChanged();
        } else {
            //pos == 0
        }
    }

    private void updateNotificationDesc(Conversation conv) {
        final IMessage imsg = conv.message;
        if (imsg == null || imsg.content.getType() != IMessage.MessageType.MESSAGE_GROUP_NOTIFICATION) {
            return;
        }
        long currentUID = this.currentUID;
        IMessage.GroupNotification notification = (IMessage.GroupNotification)imsg.content;
        if (notification.notificationType == IMessage.GroupNotification.NOTIFICATION_GROUP_CREATED) {
            if (notification.master == currentUID) {
                notification.description = String.format("您创建了\"%s\"群组", notification.groupName);
            } else {
                notification.description = String.format("您加入了\"%s\"群组", notification.groupName);
            }
        } else if (notification.notificationType == IMessage.GroupNotification.NOTIFICATION_GROUP_DISBAND) {
            notification.description = "群组已解散";
        } else if (notification.notificationType == IMessage.GroupNotification.NOTIFICATION_GROUP_MEMBER_ADDED) {
            User u = getUser(notification.member);
            if (TextUtils.isEmpty(u.name)) {
                notification.description = String.format("\"%s\"加入群", u.identifier);
                final IMessage.GroupNotification fnotification = notification;
                final Conversation fconv = conv;
                asyncGetUser(notification.member, new GetUserCallback() {
                    @Override
                    public void onUser(User u) {
                        fnotification.description = String.format("\"%s\"加入群", u.name);
                        if (fconv.message == imsg) {
                            fconv.setDetail(fnotification.description);
                        }
                    }
                });
            } else {
                notification.description = String.format("\"%s\"加入群", u.name);
            }
        } else if (notification.notificationType == IMessage.GroupNotification.NOTIFICATION_GROUP_MEMBER_LEAVED) {
            User u = getUser(notification.member);
            if (TextUtils.isEmpty(u.name)) {
                notification.description = String.format("\"%s\"离开群", u.identifier);
                final IMessage.GroupNotification fnotification = notification;
                final Conversation fconv = conv;
                asyncGetUser(notification.member, new GetUserCallback() {
                    @Override
                    public void onUser(User u) {
                        fnotification.description = String.format("\"%s\"离开群", u.name);
                        if (fconv.message == imsg) {
                            fconv.setDetail(fnotification.description);
                        }
                    }
                });
            } else {
                notification.description = String.format("\"%s\"离开群", u.name);
            }
        } else if (notification.notificationType == IMessage.GroupNotification.NOTIFICATION_GROUP_NAME_UPDATED) {
            notification.description = String.format("群组改名为\"%s\"", notification.groupName);
        }
    }

    @Override
    public void onNotification(Notification notification) {
        if (notification.name.equals(PeerMessageActivity.SEND_MESSAGE_NAME)) {
            IMessage imsg = (IMessage) notification.obj;

            int pos = findConversationPosition(imsg.receiver, Conversation.CONVERSATION_PEER);
            Conversation conversation = null;
            if (pos == -1) {
                conversation = newPeerConversation(imsg.receiver);
            } else {
                conversation = conversations.get(pos);
            }

            conversation.message = imsg;
            updateConversationDetail(conversation);

            if (pos == -1) {
                conversations.add(0, conversation);
                adapter.notifyDataSetChanged();
            } else if (pos > 0){
                conversations.remove(pos);
                conversations.add(0, conversation);
                adapter.notifyDataSetChanged();
            } else {
                //pos == 0
            }

        } else if (notification.name.equals(PeerMessageActivity.CLEAR_MESSAGES)) {
            Long peerUID = (Long)notification.obj;
            Conversation conversation = findConversation(peerUID, Conversation.CONVERSATION_PEER);
            if (conversation != null) {
                conversations.remove(conversation);
                adapter.notifyDataSetChanged();
            }
        } else if (notification.name.equals(GroupMessageActivity.SEND_MESSAGE_NAME)) {
            IMessage imsg = (IMessage) notification.obj;
            int pos = findConversationPosition(imsg.receiver, Conversation.CONVERSATION_GROUP);
            Conversation conversation = null;
            if (pos == -1) {
                conversation = newGroupConversation(imsg.receiver);
            } else {
                conversation = conversations.get(pos);
            }

            conversation.message = imsg;
            updateConversationDetail(conversation);

            if (pos == -1) {
                conversations.add(0, conversation);
                adapter.notifyDataSetChanged();
            } else if (pos > 0){
                conversations.remove(pos);
                conversations.add(0, conversation);
                adapter.notifyDataSetChanged();
            } else {
                //pos == 0
            }

        }  else if (notification.name.equals(GroupMessageActivity.CLEAR_MESSAGES)) {
            Long groupID = (Long)notification.obj;
            Conversation conversation = findConversation(groupID, Conversation.CONVERSATION_GROUP);
            if (conversation != null) {
                conversations.remove(conversation);
                adapter.notifyDataSetChanged();
            }
        }
    }

    @Override
    public void onSystemMessage(String sm) {
        try {
            String s = sm.replace("\\", "");
            Log.i(TAG, "system message:" + s);
            JSONObject object = new JSONObject(s);
            if ("im".equals(object.getString("content_type")) && "互动提醒".equals(object.getString("title"))) {
                String msgContent = object.getString("msg_content");
                if (getActivity() != null) {
                    Intent intent = new Intent();
                    intent.setAction(Constant.ACTION_VIE_ANSWER);
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.putExtra("data", msgContent);
                    LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public boolean canBack() {
        return false;
    }


    protected User getUser(long uid) {
        User u = new User();
        u.uid = uid;
        u.name = null;
        u.avatarURL = "";
        u.identifier = String.format("%d", uid);
        return u;
    }


    @SuppressLint("StaticFieldLeak")
    protected void asyncGetUser(long uid, GetUserCallback cb) {
        final long fuid = uid;
        final GetUserCallback fcb = cb;
        if (userInfoCallback != null) {
            userInfoCallback.callback(uid, cb);
        }else{
            new AsyncTask<Void, Integer, User>() {
                @Override
                protected User doInBackground(Void... urls) {
                    User u = new User();
                    u.uid = fuid;
                    u.name = String.format("%d", fuid);
                    u.avatarURL = "";
                    u.identifier = String.format("%d", fuid);
                    return u;
                }
                @Override
                protected void onPostExecute(User result) {
                    fcb.onUser(result);
                }
            }.executeOnExecutor(Executors.newCachedThreadPool());
        }
    }


    protected Group getGroup(long gid) {
        Group g = new Group();
        g.gid = gid;
        g.name = null;
        g.avatarURL = "";
        g.identifier = String.format("%d", gid);
        return g;
    }


    @SuppressLint("StaticFieldLeak")
    protected void asyncGetGroup(long gid, GetGroupCallback cb) {
        final long fgid = gid;
        final GetGroupCallback fcb = cb;
        if (groupInfoCallback != null) {
            groupInfoCallback.callback(gid, fcb);
        }else{
            new AsyncTask<Void, Integer, Group>() {
                @Override
                protected Group doInBackground(Void... urls) {
                    Group g = new Group();
                    g.gid = fgid;
                    g.name = String.format("%d", fgid);
                    g.avatarURL = "";
                    g.identifier = String.format("%d", fgid);
                    return g;
                }
                @Override
                protected void onPostExecute(Group result) {
                    fcb.onGroup(result);
                }
            }.executeOnExecutor(Executors.newCachedThreadPool());
        }
    }


    protected void onPeerClick(long uid) {
        asyncGetUser(uid, new GetUserCallback() {
            @Override
            public void onUser(User u) {
                if (conversationOnItemClickListener != null) {
                    conversationOnItemClickListener.onChat(u);
                }
            }
        });

    }


    protected void onGroupClick(long gid) {
        Log.i(TAG, "group conversation");
        asyncGetGroup(gid, new GetGroupCallback() {
            @Override
            public void onGroup(Group g) {
                if (conversationOnItemClickListener != null) {
                    conversationOnItemClickListener.onGroup(g);
                }
            }
        });

    }


    protected void onCustomerServiceClick(Conversation conv) {
        ICustomerMessage msg = (ICustomerMessage)conv.message;
        if (conversationOnItemClickListener != null) {
            conversationOnItemClickListener.onCustomer(msg);
        }
    }

    public void setConversationOnItemClickListener(ConversationOnItemClickListener conversationOnItemClickListener) {
        this.conversationOnItemClickListener = conversationOnItemClickListener;
    }

    public void setUserInfoCallback(UserInfoCallback userInfoCallback) {
        this.userInfoCallback = userInfoCallback;
    }

    public void setGroupInfoCallback(GroupInfoCallback groupInfoCallback) {
        this.groupInfoCallback = groupInfoCallback;
    }


    public interface ConversationOnItemClickListener{
        void onChat(User u);
        void onGroup(Group group);
        void onCustomer(ICustomerMessage iCustomerMessage);
        void onGroups();
        void onNotice();
    }

    public interface UserInfoCallback{
        void callback(long uid,GetUserCallback cb);
    }

    public interface GroupInfoCallback{
        void callback(long gid,GetGroupCallback cb);
    }

}
